import { AudioMgr } from '../controller/AudioMgr';
import GameCtrl from '../controller/GameCtrl';
import TeMap from '../core/TeMap';
import { PosInfo, Forward, playerState, PlayerInput, PlayerSkin, AchiveItemId } from '../define/GameDefine';
import { UICommandKey } from '../define/UICommand';
import ViewMgr from '../manager/ViewMgr';
import MapModel from '../model/MapModel';
import { Item } from '../object/Item';
import { ItemContainer } from '../object/ItemContainer';
import { ItemManager } from '../object/ItemManager';
import { MapUnit } from '../object/MapUnit';
import { GameConst, gameData } from '../tool/GameData';
import RandomTool from '../tool/RandomTool';

const MaxItem = 5;
export class Player {
  /**
   * 每个玩家的道具列表
   */
  public items: Item[] = new Array(MaxItem);

  /**
   * 初始化
   * @param part
   * @param hid
   */
  public init(part: number, hid: string): void {
    this.part = part;
    this.hid = hid;
    this.state = playerState.Ideal;
    //初始化4个方向输入状态
    this.ForwardOrder.set(Forward.Up, false);
    this.ForwardOrder.set(Forward.Down, false);
    this.ForwardOrder.set(Forward.Left, false);
    this.ForwardOrder.set(Forward.Right, false);
    this.forward = Forward.Down; //初始朝下
    // this.items[0] = new Item(AchiveItemId.Apple);
  }

  public part: number;
  public hid: string;
  public name: string;
  public positionSeed: number;
  public color: PlayerSkin;

  public nowPos: PosInfo;

  public uiFocusIndex: number = 0;

  /**
   * 从新设置当前目标
   */
  public state: playerState;
  public forward: Forward;
  public nextForward: Forward; //第二指令 加强下操作手感
  public nextPos: PosInfo;
  public ForwardOrder: TeMap<boolean> = new TeMap<boolean>(); //4方向的输入状态 true为输入状态 false为放开状态
  public resetForward(forward: Forward): void {
    // if(this.state == playerState.Run)return;
    // if(!this.checkForward(forward))return;
    this.ForwardOrder.set(forward, true); //不关的话就一直跑
    if (this.state == playerState.Run && forward != this.forward) this.nextForward = forward; //保存个第二指令
    if (this.checkForward(forward)) {
      //奔跑逻辑
      this.state = playerState.Run;
      this.forward = forward;
      this.resetNextPos();
    } else {
      if (this.state == playerState.Ideal) {
        //单纯改个方向
        this.forward = forward;
      }
    }
  }

  /**
   * 不跑了
   */
  public stop(): void {
    this.state = playerState.Ideal;
    this.nextPos = null;
  }

  /**
   * 重置奔跑方向
   * @param forward
   */
  public resetNextPos(): void {
    this.nextPos = this.getNextPos(this.forward);
  }

  /**
   * 执行第二指令
   */
  public resetNextForward(): void {
    this.forward = this.nextForward;
    this.nextForward = null;
  }

  /**
   * 达到终点
   * @param forward
   */
  public getEnd(): void {
    this.nowPos = this.nextPos;
  }

  public cancelForward(forward: Forward): void {
    this.ForwardOrder.set(forward, false); //不关的话就一直跑
    if (this.nextForward == forward) this.nextForward = null;
  }

  /**
   * 检测是否能往这个方向走
   */
  public checkForward(forward: Forward): boolean {
    if (this.state == playerState.Run && forward != this.forward) return false;
    let nextPos: PosInfo = this.getNextPos(forward);
    let mapData: MapUnit = MapModel.ins.getData(nextPos.y, nextPos.x);
    if (!mapData) return false;
    if (!mapData.checkRun()) return false;
    return true;
  }

  /**
   * 得到下一个奔跑的点
   */
  public getNextPos(forward: Forward): PosInfo {
    let x: number = this.nowPos.x;
    let y: number = this.nowPos.y;
    switch (forward) {
      case Forward.Up:
        y = y + 1;
        break;
      case Forward.Down:
        y = y - 1;
        break;
      case Forward.Left:
        x = x - 1;
        break;
      case Forward.Right:
        x = x + 1;
        break;
    }
    return { x: x, y: y };
  }

  //开始操作
  public runDeal(p: number): void {
    switch (p) {
      case cc.macro.KEY.space:
        let forwardPos: PosInfo = this.getNextPos(this.forward);
        let mapData: MapUnit = MapModel.ins.getData(forwardPos.y, forwardPos.x);
        if (mapData) {
          console.log('交互1');
          mapData.onDeal(this);
        }
        break;
      // 拾取
      case cc.macro.KEY.r:
        this.pick();
        break;
      // 丢弃
      case cc.macro.KEY.q:
        this.throwItem();
        break;
      // 使用
      case cc.macro.KEY.e:
        this.useItem();
        break;
      case cc.macro.KEY.w:
        this.uiFocusIndex = (this.uiFocusIndex % GameConst.LowLevelCount) + GameConst.LowLevelCount;
        if (this.uiFocusIndex >= GameConst.TotalUICount) {
          this.uiFocusIndex = GameConst.TotalUICount - 1;
        }
        break;
      case cc.macro.KEY.s:
        this.uiFocusIndex = this.uiFocusIndex % GameConst.LowLevelCount;
        break;
      case cc.macro.KEY.a:
        this.uiFocusIndex--;
        if (this.uiFocusIndex < 0) {
          this.uiFocusIndex = GameConst.TotalUICount;
        }
        break;
      case cc.macro.KEY.d:
        this.uiFocusIndex++;
        if (this.uiFocusIndex >= GameConst.TotalUICount) {
          this.uiFocusIndex = 0;
        }
        break;
    }
  }

  public throwItem() {
    const item = this.items[this.uiFocusIndex];
    if (item) {
      this.items[this.uiFocusIndex] = undefined;
      const mapUint = MapModel.ins.getData(this.nowPos.y, this.nowPos.x);
      mapUint.throwItem(item);
    }
  }

  public useItem() {
    const item = this.items[this.uiFocusIndex];

    if (!item) {
      return;
    }

    switch (item.id) {
      case AchiveItemId.Steal:
        ViewMgr.ins.hint(this.hid + '使用' + item.name);
        this.items[this.uiFocusIndex] = undefined;
        this.steal();
        break;
    }
    //ViewMgr.ins.hint(this.hid+"使用"+item.name);
  }

  public pickItem(item: Item, slot: number) {
    if (this.hid == gameData.myPlayer.hid) {
      ViewMgr.ins.hint('得到' + item.name);
      AudioMgr.inst.playSoundLocal('get');
    }
    this.items[slot] = item;
    const { winType, winIds } = ItemManager.CheckSuccessed(this.items);
    if (winType >= 0) {
      ViewMgr.ins.emit(UICommandKey.gameEnd, { winType, winPlayer: this.hid, winIds });
    }
  }

  private pick() {
    const mapUint = MapModel.ins.getData(this.nowPos.y, this.nowPos.x);
    const item = mapUint.pickItem();
    if (item === null || item === undefined) {
      return;
    }
    const emptySlot = this.getBagEmptySlot();
    if (emptySlot === null) {
      return false;
    }

    this.pickItem(item, emptySlot);
    return true;
  }

  /**
   *
   * @returns 第几格的位置，null 为无位置
   */
  public getBagEmptySlot(): number | null {
    const items = this.items;
    for (let i = 0; i < items.length; i++) {
      if (!items[i]) {
        return i;
      }
    }
    return null;
  }

  /**
   *
   * @returns 获得一个随机的道具位置 必须要有道具
   */
  public getRandomSlot(): number | null {
    const items = this.items;
    let arr: number[] = [];
    for (let i = 0; i < items.length; i++) {
      if (!items[i]) {
        continue;
      } else {
        arr.push(i);
      }
    }
    let index: number;
    if (arr.length > 0) {
      let rIndex = Math.floor(arr.length * RandomTool.getRandom());
      index = arr[rIndex];
    }
    return index;
  }

  public steal() {
    const otherPlayer = GameCtrl.inst.getEnemyplayer(this.hid);
    const item = otherPlayer.beStealed();
    if (item) {
      const slot = this.getBagEmptySlot();
      this.pickItem(item, slot);
      ViewMgr.ins.hint(`你偷到了${item.name}`, this.hid);
    } else {
      ViewMgr.ins.hint('你啥也没偷到', this.hid);
    }
  }

  public beStealed(): Item | null {
    for (let i = 0; i < this.items.length; i++) {
      const item = this.items[i];
      if (item) {
        ViewMgr.ins.hint(`你的${item.name}被偷了`, this.hid);
        this.items[i] = undefined;
        console.log(this.items);
        return item;
      }
    }
    return null;
  }

  //操作完成
  public dealOver(): void {
    //this.state = playerState.Ideal;
  }
}
